tmap.Tmap = zk.$extends(zul.Widget, {
    /**
     * anchor: 控件停靠位置(左上，右上，左下，右下)
     * offset: 控件的偏移值(x，y)
     */
    _map: null,
    _mapStyle: "",
    _areaStyle: null,
    _enableMapClick: true,
    _infobox: true,
    _zoom: 15,
    _dragging: true,
    _scrollWheelZoom: true,
    _doubleClickZoom: true,
    _pinchToZoom: true,
    _choosePoint: false,           //拖拽选点
    _scaleControl: false,          //比例尺
    _scaleAnchor: "",
    _scaleOffset: "",
    _copyrightControl: false,      //版权信息
    _copyrightAnchor: "",
    _copyrightOffset: "",
    _copyrightContent: "",
    _maptypeControl: false,        //地图类型
    _maptypeAnchor: "",
    _maptypeOffset: "",
    _maptypeStyle: "",
    _maptypeArray: "",
    _trafficControl: false,        //路况图层
    _trafficAnchor: "",
    _trafficOffset: "",
    _navigationControl: false,     //平移缩放
    _navigationAnchor: "",
    _navigationOffset: "",
    _navigationStyle: "",
    _geolocationControl: false,    //定位控件
    _geolocationAnchor: "",
    _geolocationOffset: "",
    _geolocationIcon: "",
    _autoLocation: false,
    _overviewMapControl: false, //缩略地图
    _overviewMapAnchor: "",
    _overviewMapOffset: "",
    _overviewMapSize: "",
    _drawingManager: false, //绘制工具
    _drawingMode: "",
    _drawingManagerAnchor: "",
    _drawingManagerOffset: "",
    _drawingData: null,
    _marks: null,             //覆盖物
    _markerClusterer: false,    //点聚合
    _customMarks: null,     //自定义覆盖物
    _position: null,    //目标位置
    _positionMark: null,    //位置标记、提示
    _positionMarkSize: null,
    _drivingRoute: false,
    _drivingRoutePoints: null,
    drivingZoomCtrl: null,
    drivingRouteData: {},
    markers: null,

    $define: {
        map: function (val) {
        },
        mapStyle: function () {
        },
        areaStyle: function (val) {
            if (!!this._map)
                this.drawAreaBoundary();
        },
        enableMapClick: function (val) {
        },
        infobox: function (val) {
        },
        zoom: function (val) {
            if (!(!this._map))
                this.setMapZoom();
        },
        dragging: function (val) {
        },
        scrollWheelZoom: function (val) {
        },
        doubleClickZoom: function (val) {
        },
        pinchToZoom: function (val) {
        },
        choosePoint: function (val) {
            if (!!this._map && val)
                this.showChooseIcon();
        },
        scaleControl: function (val) {
        },
        scaleAnchor: function (val) {
        },
        scaleOffset: function (val) {
        },
        copyrightControl: function (val) {
        },
        copyrightAnchor: function (val) {
        },
        copyrightOffset: function (val) {
        },
        copyrightContent: function (val) {
        },
        maptypeControl: function (val) {
        },
        maptypeAnchor: function (val) {
        },
        maptypeOffset: function (val) {
        },
        maptypeStyle: function (val) {
        },
        maptypeArray: function (val) {
        },
        trafficControl: function (val) {
        },
        trafficAnchor: function (val) {
        },
        trafficOffset: function (val) {
        },
        navigationControl: function (val) {
        },
        navigationAnchor: function (val) {
        },
        navigationOffset: function (val) {
        },
        navigationStyle: function (val) {
        },
        geolocationControl: function (val) {
        },
        geolocationAnchor: function (val) {
        },
        geolocationOffset: function (val) {
        },
        geolocationStyle: function (val) {
        },
        autoLocation: function (val) {
            if (!(!this._map))
                this.geoLocation();
        },
        overviewMapControl: function (val) {
        },
        overviewMapAnchor: function (val) {
        },
        overviewMapOffset: function (val) {
        },
        overviewMapSize: function (val) {
        },
        drawingManager: function (val) {
        },
        drawingMode: function (val) {
        },
        drawingManagerAnchor: function (val) {
        },
        drawingManagerOffset: function (val) {
        },
        drawingData: function (val) {
            if (!(!this._map))
                this.showDrawing();
        },
        marks: function (val) {
            if (!(!this._map))
                this.showMarkers();
        },
        markerClusterer: function (val) {
        },
        customMarks: function (val) {
            if (!(!this._map))
                this.showCustomMarks();
        },
        position: function (val) {
            if (!(!this._map)) {
                if (!(!val)) {
                    if (val.indexOf(',') > -1) {
                        this.goPosition(val);
                    } else {
                        var that = this;
                        var geoc = new T.Geocoder();
                        geoc.getPoint(val, function (r) {
                            that.goPosition(r.lng + ',' + r.lat);
                        })
                    }
                }
            }
        },
        positionMark: function (v) {
        },
        positionMarkSize: function (v) {
        },
        drivingRoute: function (v) {
            if (!(!this._map)) {
                if (v) {
                    this._map.addControl(this.drivingZoomCtrl);
                } else {
                    this._map.removeControl(this.drivingZoomCtrl);
                }
            }
        },
        drivingRoutePoints: function (v) {
            if (!(!this._map)) {
                try {
                    var point = v;
                    if (point.length < 4) {
                        return;
                    } else if (point.length === 4) {
                        this.drivingSearch(new T.LngLat(point[0], point[1]), new T.LngLat(point[2], point[3]), null);
                    } else {
                        this.drivingSearch(new T.LngLat(point[0], point[1]), new T.LngLat(point[2], point[3]), point[4]);
                    }
                } catch (e) {
                    console.log(e);
                    return e;
                }
            }
        }
    },

    redraw: function (out) {
        out.push('<div id="', this.uuid, '"', this.domAttrs_(), '/>');
    },

    domAttrs_: function () {
        var attr = this.$supers('domAttrs_', arguments);
        attr += ' style="width:100%;height:100%;"';
        return attr;
    },

    bind_: function () {
        this.$supers(tmap.Tmap, 'bind_', arguments);
        this._init();
    },

    unbind_: function () {
        this.$supers(tmap.Tmap, 'unbind_', arguments);
    },

    doClick_: function () {
    },

    _init: function () {
        var that = this;
        jq.getScript("//api.tianditu.gov.cn/api?v=4.0&tk=60bdc479a74af2ff0cb33da5176227d3").done(function () {
            that._map = new T.Map(that.uuid);
            if (!that._map)
                return;
            var tmap = that._map;
            let centerPoint = new T.LngLat(116.40769, 39.89945); //地图中心点，默认故宫
            if (!!that._position) {
                if (that._position.indexOf(',') > -1) {
                    centerPoint = new T.LngLat(that._position.split(",")[0], that._position.split(",")[1]);
                    tmap.centerAndZoom(centerPoint, that._zoom);
                    that.initFunc();
                } else {
                    var geocoder = new T.Geocoder();
                    geocoder.getPoint(that._position, function (r) {
                        centerPoint = r.getLocationPoint();
                        tmap.centerAndZoom(centerPoint, that._zoom);
                        that.initFunc();
                    })
                }
            }else {
                tmap.centerAndZoom(centerPoint, that._zoom);
                that.initFunc();
            }

            //缩放事件
            tmap.addEventListener('zoomend', function (e) {
                if (!!that._customMarks) {
                    tmap.clearOverLays();
                    that.showCustomMarks();
                }
            });

            //拖拽事件
            tmap.addEventListener('dragend', function (e) {
                if (!!that._customMarks) {
                    that.showCustomMarks();
                }
            });

        });
    },

    initFunc: function () {
        // 获取当前定位
        if (this._autoLocation) {
            if (this._position == null || this._position === "")
                this.geoLocation();
        }

        // 初始化覆盖物
        if (!(!this._marks)) {
            this.showMarkers();
        }

        // 自定义覆盖物
        if (!!this._customMarks)
            this.showCustomMarks();
    },

    search: function (name) {
        let self = this;
        var local = null;
        var options = {
            onSearchComplete: function (results) {
                self.fire("onSearch", {pois: results.getPois()});
            }
        };
        local = new T.LocalSearch(this._map, options);
        local.search(name);
    },

    clearOverlays: function () {
        if (!!this._map)
            this._map.clearOverLays();
    },

    geoLocation: function () {
        var self = this;
        if (navigator.geolocation) {
            navigator.geolocation.getCurrentPosition(function (position) {
                let lat = position.coords.latitude;
                let lng = position.coords.longitude;
                // alert(lng+","+lat);
                var loc = new T.LngLat(lng,lat);
                self._map.centerAndZoom(loc, 15);
                var marker = new T.Marker(loc);
                self._map.addOverLay(marker);
                var coder = new T.Geocoder();
                coder.getLocation(loc, function (result) {
                    self.fire("onLocation", {
                        point: loc,
                        address: result.getAddress(),
                        addressComponent: result.getAddressComponent()
                    });
                })
            },function (err) {
                tmapLocation();
            })
        }else {
            tmapLocation();
        }
        function tmapLocation(){
            var geo = new T.Geolocation();
            geo.getCurrentPosition(function (e) {
                // alert(JSON.stringify(e));
                self._map.centerAndZoom(e.lnglat, 15);
                var marker = new T.Marker(e.lnglat);
                self._map.addOverLay(marker);
                var coder = new T.Geocoder();
                coder.getLocation(e.lnglat, function (result) {
                    self.fire("onLocation", {
                        point: e.lnglat,
                        address: result.getAddress(),
                        addressComponent: result.getAddressComponent()
                    });
                })
            });
        }
        self._autoLocation = null;
    },

    //点聚合
    showMarkers: function () {
        var that = this;
        this.markers = [];
        for (let i = 0; i < this._marks.length; i++) {
            let marker = new T.Marker(new T.LngLat(this._marks[i][0], this._marks[i][1]));
            if (!!this._marks[i][3]) {
                let iconsize = "20,20";
                if (!!this._marks[i][4])
                    iconsize = this._marks[i][4];
                let markicon = new T.Icon({iconUrl: this._marks[i][3], iconSize: this.getOffset(iconsize), iconAnchor: this.getOffset(iconsize)});
                marker = new T.Marker(new T.LngLat(this._marks[i][0], this._marks[i][1]), {icon: markicon});
            }
            if (!(!this._marks[i][2])) {
                this.addClickHandler(marker, this._marks[i][2]);
            }
            marker.addEventListener("dblclick", function () {
                that._map.centerAndZoom(new T.LngLat(that._marks[i][0], that._marks[i][1]), 18);
            });
            let iconmarker = null;
            if (!!this._marks[i][5]) {
                let size = "100,100";
                if (!!this._marks[i][6])
                    size = this._marks[i][6];
                let mapicon = new T.Icon({iconUrl: this._marks[i][5], iconSize: this.getOffset(size), iconAnchor: this.getOffset(size)});
                iconmarker = new T.Marker(new T.LngLat(this._marks[i][0], this._marks[i][1]), {icon: mapicon});
            }

            if (this._markerClusterer) {
                this.markers.push(marker);
            } else {
                this._map.addOverLay(iconmarker);
                this._map.addOverLay(marker);
            }
        }
        if (this._markerClusterer)
            var markerClusterer = new T.MarkerClusterer(this._map, {markers: this.markers});
    },

    //渲染自定义覆盖物
    showCustomMarks: function () {
        if (Array.isArray(this._customMarks)) {
            var that = this;
            var overlays = that._map.getOverlays();
            for (let i = 0; i < that._customMarks.length; i++) {
                if (that._customMarks[i][0].indexOf("-") > 0) {
                    let zoomArr = that._customMarks[i][0].split("-");
                    if (zoomArr[0] <= that._map.getZoom() && that._map.getZoom() <= zoomArr[1]) {
                        if (this.isPointInMap(new T.LngLat(that._customMarks[i][1], that._customMarks[i][2]))) {
                            let flag = null;
                            for (let j = 0; j < overlays.length; j++) {
                                if (overlays[j].point != null && overlays[j].point.lng === that._customMarks[i][1] && overlays[j].point.lat === that._customMarks[i][2])
                                    flag = true;
                            }
                            //判断地图是否已存在该覆盖物
                            if (!flag)
                                that.drawCustomOverlay(that._customMarks[i]);
                        }
                    }
                }
            }
        }
    },

    // 添加单个自定义覆盖物
    drawCustomOverlay: function (markData) {
        var map = this._map;
        var myLabel = new T.Label({text: markData[3], position: new T.LngLat(markData[1], markData[2])});
        myLabel.setBorderLine();
        myLabel.setBorderColor();
        myLabel.setBackgroundColor();
        if (!!markData[4]) {
            if (markData[4].indexOf(",") > 0) {
                var offset = markData[4].split(",");
                myLabel.setOffset(new T.Point(Number(offset[0]), Number(offset[1])));
            }
        }
        myLabel.addEventListener("click", function () {
            map.centerAndZoom(myLabel.getLngLat(), map.getZoom() + 2);
        });
        map.addOverLay(myLabel);
    },

    /**
     * 判断点在地图可视范围内
     * @param point
     * @returns {boolean}
     */
    isPointInMap: function (point) {
        if (!(point instanceof T.dq)) {
            return false;
        }
        var bounds = this._map.getBounds();
        var sw = bounds.getSouthWest();
        var ne = bounds.getNorthEast();
        return (point.lng >= sw.lng && point.lng <= ne.lng && point.lat >= sw.lat && point.lat <= ne.lat);
    },

    /**
     * 获得图形的中心点
     */
    getCenterPoint: function (path) {
        var x = 0.0;
        var y = 0.0;
        for (var i = 0; i < path.length; i++) {
            x = x + parseFloat(path[i].lng);
            y = y + parseFloat(path[i].lat);
        }
        x = x / path.length;
        y = y / path.length;
        return new T.Point(x, y);
    },

    setMapZoom: function () {
        this._map.setZoom(this._zoom);
    },

    getPoint: function (pointstr) {
        var temp = pointstr.split(',');
        return new T.LngLat(temp[0], temp[1]);
    },

    goPosition: function (p) {
        let point = this.getPoint(p);
        if (!(!this._positionMark)) {
            let icon_mk = null;
            if (this._positionMark === "default") {
                icon_mk = new T.Marker(point);
            } else {
                if (!this._positionMarkSize)
                    this._positionMarkSize = "100,100";
                let mapicon = new T.Icon(this._positionMark, this.getOffset(this._positionMarkSize));
                mapicon.setIconSize(this.getOffset(this._positionMarkSize));
                icon_mk = new T.Marker(point, {icon: mapicon});
            }
            this._map.addOverlay(icon_mk);
        }
        // this._map.panTo(point);
        this._map.centerAndZoom(point, this._zoom);
    },

    // 移动到指定位置
    panTo: function (location) {
        // console.log(location);
        this._map.panTo(location);
    },

    // 点击事件绑定
    addClickHandler: function (marker, content) {
        var opts = {
            width: 250,     // 信息窗口宽度
            height: 80,     // 信息窗口高度
            // title: "详细信息", // 信息窗口标题
            enableMessage: true//设置允许信息窗发送短息
        };
        // var p = e.target;
        // var point = new T.LngLat(p.getPosition().lng, p.getPosition().lat);
        var infoWindow = new T.InfoWindow();  // 创建信息窗口对象
        infoWindow.setContent(content);
        marker.addEventListener("click", function (e) {
            this.openInfoWindow(infoWindow); //开启信息窗口
        })
    },

    // 获取停靠位置
    getAnchor: function (e) {
        switch (e.toUpperCase()) {
            case "TOP_LEFT":
                return BMAP_ANCHOR_TOP_LEFT;
                break;
            case "TOP_RIGHT":
                return BMAP_ANCHOR_TOP_RIGHT;
                break;
            case "BOTTOM_LEFT":
                return BMAP_ANCHOR_BOTTOM_LEFT;
                break;
            case "BOTTOM_RIGHT":
                return BMAP_ANCHOR_BOTTOM_RIGHT;
                break;
        }
    },

    // 获取偏移值
    getOffset: function (e) {
        if (e.indexOf(",") > 0) {
            let size = e.split(",");
            return new T.Point(parseInt(size[0]), parseInt(size[1]));
        }
        return null;
    },

    // 获取地图类型控件样式
    getMapType: function (e) {
        switch (e.toUpperCase()) {
            case "HORIZONTAL":
                return BMAP_MAPTYPE_CONTROL_HORIZONTAL;
                break;
            case "DROPDOWN":
                return BMAP_MAPTYPE_CONTROL_DROPDOWN;
                break;
            case "MAP":
                return BMAP_MAPTYPE_CONTROL_MAP;
                break;
        }
    },

    // 获取地图类型控件样式
    getMapArray: function (e) {
        e = e.split(",");
        let array = [];
        e.forEach(item => {
            switch (item.toUpperCase()) {
                case "NORMAL":
                    array.push(BMAP_NORMAL_MAP);
                    break;
                case "SATELLITE":
                    array.push(BMAP_SATELLITE_MAP);
                    break;
                case "HYBRID":
                    array.push(BMAP_HYBRID_MAP);
                    break;
            }
        });
        return array;
    },

    // 获取平移缩放控件样式
    getNavigationType: function (e) {
        switch (e.toUpperCase()) {
            case "LARGE":
                return BMAP_NAVIGATION_CONTROL_LARGE;
                break;
            case "SMALL":
                return BMAP_NAVIGATION_CONTROL_SMALL;
                break;
            case "PAN":
                return BMAP_NAVIGATION_CONTROL_PAN;
                break;
            case "ZOOM":
                return BMAP_NAVIGATION_CONTROL_ZOOM;
                break;
        }
    },

    // 获取地图类型控件样式
    getModes: function (e) {
        e = e.split(",");
        let array = [];
        e.forEach(item => {
            switch (item.toUpperCase()) {
                case "MARKER":
                    array.push(BMAP_DRAWING_MARKER);
                    break;
                case "CIRCLE":
                    array.push(BMAP_DRAWING_CIRCLE);
                    break;
                case "POLYLINE":
                    array.push(BMAP_DRAWING_POLYLINE);
                    break;
                case "POLYGON":
                    array.push(BMAP_DRAWING_POLYGON);
                    break;
                case "RECTANGLE":
                    array.push(BMAP_DRAWING_RECTANGLE);
                    break;
            }
        });
        return array;
    },

    /**
     * 百度坐标转换为天地图
     * @param bd_lng
     * @param bd_lat
     */
    transformBaidu: function (bd_lng,bd_lat) {
        //百度坐标转火星坐标
        var x_pi=3.14159265358979324 * 3000.0 / 180.0;
        var mars_point={lng:0,lat:0};
        var x=bd_lng-0.0065;
        var y=bd_lat-0.006;
        var z=Math.sqrt(x*x+y*y)- 0.00002 * Math.sin(y * x_pi);
        var theta = Math.atan2(y, x) - 0.000003 * Math.cos(x * x_pi);
        mars_point.lng=z * Math.cos(theta);
        mars_point.lat=z * Math.sin(theta);
        return this.gcj02Towgs84(mars_point.lng, mars_point.lat);
    },

    /**
     * 火星坐标转地球坐标
     * @param lon
     * @param lat
     * @returns {{lat: (number|*), lon: (number|*)}}
     */
    gcj02Towgs84: function (lon, lat) {
        var PI = 3.14159265358979324;
        let a = 6378245.0; //  a: 卫星椭球坐标投影到平面地图坐标系的投影因子。
        let ee = 0.00669342162296594323; //  ee: 椭球的偏心率。
        let dLat = this.transformLat(lon - 105.0, lat - 35.0);
        let dLon = this.transformLon(lon - 105.0, lat - 35.0);
        let radLat = lat / 180.0 * PI;
        let magic = Math.sin(radLat);
        magic = 1 - ee * magic * magic;
        let sqrtMagic = Math.sqrt(magic);
        dLat = (dLat * 180.0) / ((a * (1 - ee)) / (magic * sqrtMagic) * PI);
        dLon = (dLon * 180.0) / (a / sqrtMagic * Math.cos(radLat) * PI);
        return {'lng': lon-dLon, 'lat': lat-dLat,}
    },

    transformLat: function (x, y) {
        var PI = 3.14159265358979324;
        let ret = -100.0 + 2.0 * x + 3.0 * y + 0.2 * y * y + 0.1 * x * y + 0.2 * Math.sqrt(Math.abs(x));
        ret += (20.0 * Math.sin(6.0 * x * PI) + 20.0 * Math.sin(2.0 * x * PI)) * 2.0 / 3.0;
        ret += (20.0 * Math.sin(y * PI) + 40.0 * Math.sin(y / 3.0 * PI)) * 2.0 / 3.0;
        ret += (160.0 * Math.sin(y / 12.0 * PI) + 320 * Math.sin(y * PI / 30.0)) * 2.0 / 3.0;
        return ret;
    },

    transformLon: function (x, y) {
        var PI = 3.14159265358979324;
        let ret = 300.0 + x + 2.0 * y + 0.1 * x * x + 0.1 * x * y + 0.1 * Math.sqrt(Math.abs(x));
        ret += (20.0 * Math.sin(6.0 * x * PI) + 20.0 * Math.sin(2.0 * x * PI)) * 2.0 / 3.0;
        ret += (20.0 * Math.sin(x * PI) + 40.0 * Math.sin(x / 3.0 * PI)) * 2.0 / 3.0;
        ret += (150.0 * Math.sin(x / 12.0 * PI) + 300.0 * Math.sin(x / 30.0 * PI)) * 2.0 / 3.0;
        return ret;
    }
});
